<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /*
          ES6新特性   
            let和const
              会产生块级作用域
              不会变量提升
              不能重复声明
              const定义的量值不能发生变化
            解构赋值
            三点运算符/扩展运算符/点点点运算符 
            模板字符串
            对象简写
            Symbol 新的基本数据类型，主要用来作为对象唯一属性名

            箭头函数
              和普通函数有什么区别
            模块化语法  import / export

            Proxy 代理
            Map / Set / WeakMap / WeakSet
              Map 相当于对象，存储键值对数据
                特点：key可以是任意类型
              Set 相当于数组
                特点：值是唯一的
              WeakMap: 相当于map容器
                特点: 
                  1. key只能是对象类型
                  2. 一旦key对应对象，外部没有变量引用，会被垃圾回收机制回收
              WeakSet: 相当于set容器
                特点: 
                  1. 值只能是对象类型
                  2. 一旦值对应对象，外部没有变量引用，会被垃圾回收机制回收
            
            Promise
            class & extends 继承
            
            更多语法：https://es6.ruanyifeng.com/#docs/proxy
        */

      const map = new Map();
      map.set({ name: "jack" }, { age: 18 });
      console.log(map);

      const set = new Set();
      set.add(11);
      set.add(33);
      set.add(11);
      set.add(22);
      console.log(set);

      const weakMap = new WeakMap();
      // weakMap.set(111, { age: 18 }); // Uncaught TypeError: Invalid value used as weak map key
      // weakMap.set({ name: "jack" }, { age: 18 });
      let obj = { name: "jack" };
      weakMap.set(obj, { age: 18 });
      obj = null;
      console.log(weakMap);

      // class Father {}
      // class Son extends Father {
      //   constructor(name, age) {
      //     super();
      //     this.name = name;
      //     this.age = age;
      //   }
      // }

      // 组合式继承
      function Father(sex) {
        this.sex = sex;
      }
      Father.prototype.setSex = function (sex) {
        this.sex = sex;
      };
      function Son(name, age, sex) {
        this.name = name;
        this.age = age;
        Father.call(this, sex); // 得到属性
      }
      Son.prototype.__proto__ = Father.prototype; // 得到原型上方法
      Son.prototype.setName = function (name) {
        this.name = name;
      };

      const person = {
        name: "jack",
        age: 18,
      };

      const proxy = new Proxy(person, {
        get(target, key, receiver) {
          /*
            target 就是原对象 person
            key 读取对象的某个属性
            receiver 代理返回的对象 proxy
          */
          console.log("触发get");
          return target[key];
        },
        set(target, key, val, receiver) {
          /*
            target 就是原对象 person
            key 读取对象的某个属性
            val 设置的新值
            receiver 代理返回的对象 proxy
          */
          console.log("触发set");
          target[key] = val;
        },
      });
    </script>
  </body>
</html>
